﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Entity.Infrastructure;
using XTeam.Core.Interface;
using System.Data.Entity;

namespace XTeam.Core.Abstract
{
    public abstract class DBCore<T> : DbCore, IDBCore<T> where T : class,new()
    {

        /// <summary>
        /// 查找
        /// </summary>
        public T Find(Func<T, bool> filter)
        {
            return this.Find<T>(filter);
        }

        /// <summary>
        /// 搜索
        /// </summary>
        public virtual IEnumerable<T> Search(Func<T, bool> filter)
        {
            return this.Search<T>(filter);
        }

        /// <summary>
        /// 批量更新
        /// </summary>
        public virtual int Update(IList<T> entities, Func<T, object> fileds, bool withOut)
        {
            return this.Update<T>(entities, fileds, withOut);
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        public virtual int Delete(IList<T> entities)
        {
            return this.Delete<T>(entities);
        }

        /// <summary>
        /// 批量增加
        /// </summary>
        public virtual int Append(IList<T> entities)
        {
            return this.Append<T>(entities);
        }


        protected override DbContext CreateDb()
        {
            throw new NotImplementedException();
        }
    }

    public abstract class DbCore : IDbCore
    {

        /// <summary>
        /// 连接字符串
        /// </summary>
        protected string _connectionString;
        /// <summary>
        /// 构造函数
        /// </summary>
        public DbCore()
        {

        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        public DbCore(string connectionString)
        {
            this._connectionString = connectionString;
        }

        /// <summary>
        /// 查找
        /// </summary>
        public virtual T Find<T>(Func<T, bool> filter) where T : class, new()
        {
            using (var dbContext = this.CreateDb())
            {
                var dbset = dbContext.Set<T>();
                return dbset.SingleOrDefault(filter);
            }
        }
        /// <summary>
        /// 搜索
        /// </summary>
        public virtual IEnumerable<T> Search<T>(Func<T, bool> filter) where T : class, new()
        {
            int totalRows = 0;
            return this.Search<T>(filter, 0, int.MaxValue, out totalRows);
        }

        public virtual IEnumerable<T> Search<T>(Func<T, bool> filter, int pageIndex, int pageSize, out int totalRows) where T : class, new()
        {
            var db = this.CreateDb();
            var dbset = db.Set<T>();

            IEnumerable<T> query = null;

            if (filter != null)
            {
                query = dbset.Where(filter);
            }
            else
            {
                query = dbset.Select(i => i);
            }

            totalRows = query.Count();
            var resultTable = query.Skip((pageIndex - 1) * pageSize)
                  .Take(pageSize);

            return resultTable;

        }
        /// <summary>
        /// 批量删除
        /// </summary>
        public virtual int Update<T>(IList<T> entities, Func<T, object> fileds, bool withOut = false) where T : class, new()
        {

            using (var dbContext = this.CreateDb())
            {
                foreach (var item in entities)
                {
                    var entry = dbContext.Entry(item);

                    if (null == fileds)
                    {
                        // 全部更新
                        entry.State = EntityState.Modified;
                    }
                    else
                    {
                        // 按需更新
                        #region 按需更新

                        var tempFileds = this.GetProperties(fileds(item));
                        entry.State = EntityState.Unchanged;
                        if (!withOut)
                        {
                            // 更新指定的字段
                            foreach (var filed in tempFileds)
                            {
                                entry.Property(filed).IsModified = true;
                            }
                        }
                        else
                        {
                            // 排除指定的字段
                            foreach (var filed in entry.CurrentValues.PropertyNames.Except(tempFileds))
                            {
                                entry.Property(filed).IsModified = true;
                            }
                        }
                        #endregion
                    }

                }
                return dbContext.SaveChanges();
            }
        }

        #region private

        /// <summary>
        /// 类型属性缓存
        /// </summary>
        private static Dictionary<Type, IList<string>> _propertyiesCache = new Dictionary<Type, IList<string>>();
        /// <summary>
        /// 缓存类属性
        /// </summary>
        private IList<string> GetProperties(object obj)
        {
            Type type = obj.GetType();
            IList<string> propertyies = new List<string>();
            if (!_propertyiesCache.ContainsKey(type))
            {
                foreach (var item in type.GetProperties())
                {
                    propertyies.Add(item.Name);
                }

                _propertyiesCache.Add(type, propertyies);
            }

            propertyies = _propertyiesCache[type];
            return propertyies;
        }

        #endregion

        /// <summary>
        /// 批量删除
        /// </summary>
        public virtual int Delete<T>(IList<T> entities) where T : class, new()
        {
            using (var dbContext = this.CreateDb())
            {
                foreach (var item in entities)
                {
                    dbContext.Entry<T>(item).State = EntityState.Deleted;
                }
                return dbContext.SaveChanges();
            }
        }
        /// <summary>
        /// 批量增加
        /// </summary>
        public virtual int Append<T>(IList<T> entities) where T : class, new()
        {
            using (var dbContext = this.CreateDb())
            {
                foreach (var item in entities)
                {
                    var entry = dbContext.Entry<T>(item);
                    entry.State = EntityState.Added;
                }

                return dbContext.SaveChanges();
            }
        }

        protected abstract DbContext CreateDb();

        public IQueryable<T> AsQueryable<T>() where T : class, new()
        {
            throw new NotImplementedException();
        }
    }
}
